package crafex.engine.level;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import crafex.engine.entities.Entity;
import crafex.engine.system.Console;
import crafex.engine.system.Crafex;
import crafex.engine.tools.Button;
import crafex.engine.tools.FloatVertex2D;
import crafex.engine.tools.IntVertex2D;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.KeyEvent;
import android.view.MotionEvent;



public class Level implements Serializable{
	
	/**serial number thing*/
	private static final long serialVersionUID = -105562361148834613L;
	/**last time touched*/
	protected static long lastTouchTime;
	/**list of all the GUI elements*/
	protected static ArrayList<Button> GUI = new ArrayList<Button>();
	/**list of all the enamies in the game*/
	protected static ArrayList<Entity> enamies = new ArrayList<Entity>();
	/**list of all the objects in the game*/
	protected static ArrayList<Entity> objects = new ArrayList<Entity>();
	/**list of all the scenery in the game*/
	protected static ArrayList<Entity> scenery = new ArrayList<Entity>();
	/**list of all the items in the game*/
	protected static ArrayList<Entity> items = new ArrayList<Entity>();
	/**list of all projectiles*/
	protected static ArrayList<Entity> projectiles = new ArrayList<Entity>();
	/**the background of the level or menu background if in menu*/
	public static Bitmap background = null;
	/**prev level to go to when back is pressed*/
	private Level prevLevel;
	
	/**the bounderys for the player*/
	public static IntVertex2D bounds;
	/**the amount the player has moved the view of the game map*/
	public static FloatVertex2D scroll;
	
	public Level(IntVertex2D bounds){
		scroll = new FloatVertex2D();
		Level.bounds = bounds;
		LevelHandler.setPlaying(true);
	}
	
	public Level(IntVertex2D bounds, Level prevLevel){
		this.prevLevel = prevLevel;
		scroll = new FloatVertex2D();
		Level.bounds = bounds;
		LevelHandler.setPlaying(true);
	}
	
	public void loadStart(){
		
	}
	
	public void createGUI(){
		
	}
	
	/**
	 * resets all static varalbes beside the GUI and bounds;
	 * enamies
	 * objects
	 * projectiles
	 * background
	 * scroll
	 */
	public void resetStatics(){
		enamies.clear();
		objects.clear();
		scenery.clear();
		items.clear();
		projectiles.clear();
		background = null;
		scroll.reset();
	}
	
	/**
	 * resets all static varalbes beside the GUI;
	 * enamies
	 * objects
	 * projectiles
	 * background
	 * bounds
	 * scroll
	 */
	public void resetStatics(IntVertex2D bounds){
		Level.bounds = bounds;
		enamies.clear();
		objects.clear();
		scenery.clear();
		items.clear();
		projectiles.clear();
		background = null;
		scroll.reset();
	}
	
	public void gotoPrev(){
		if(prevLevel != null){
			LevelHandler.setLevel(prevLevel);
		}
	}

	/**
	 * gets GUI list 
	 * @return GUI list
	 */
	public static List<Button> getGUI() {
		return GUI;
	}
	
	/**
	 * sets the GUI list
	 * @param buttons GUI
	 */
	protected static void setGUI(ArrayList<Button> buttons){
		GUI = buttons;
	}
	
	/**
	 * adds an element to the GUI
	 * @param button
	 */
	protected static void addToGUI(Button button){
		GUI.add(button);
	}
	
	/**
	 * removes an emement from the GUI
	 * @param index
	 */
	protected static void removeFromGUI(int index){
		GUI.remove(index);
	}

	/**
	 * clears the GUI list
	 */
	protected static void clearGUI() {
		GUI.clear();
	}
	
	public static ArrayList<Entity> getEnamies() {
		return enamies;
	}

	public static void setEnamies(ArrayList<Entity> enamies) {
		Level.enamies = enamies;
	}

	public static ArrayList<Entity> getObjects() {
		return objects;
	}

	public static void setObjects(ArrayList<Entity> objects) {
		Level.objects = objects;
	}

	public static ArrayList<Entity> getScenery() {
		return scenery;
	}

	public static void setScenery(ArrayList<Entity> scenery) {
		Level.scenery = scenery;
	}

	public static ArrayList<Entity> getItems() {
		return items;
	}

	public static void setItems(ArrayList<Entity> items) {
		Level.items = items;
	}

	public static ArrayList<Entity> getProjectiles() {
		return projectiles;
	}

	public static void setProjectiles(ArrayList<Entity> projectiles) {
		Level.projectiles = projectiles;
	}

	public static IntVertex2D getBounds() {
		return bounds;
	}

	public static void setBounds(IntVertex2D bounds) {
		Level.bounds = bounds;
	}

	public static FloatVertex2D getScroll() {
		return scroll;
	}

	/**
	 * moves the view to the correct place for the player to be able to best see the area
	 * @param scroll
	 */
	public void scroll(FloatVertex2D scroll){
		Level.scroll.addToX(scroll.getX());
		Level.scroll.addToY(scroll.getY());
	}
	
	public static void scroll(FloatVertex2D movement, FloatVertex2D coordinates){
		if(scroll.getX() < bounds.getX() && coordinates.getX() > (Crafex.getScreenWidth() * .6)){
			if(movement.getX() <= bounds.getX() - scroll.getX() ){
				scroll.addToX(movement.getX());
			}else{
				scroll.setX(bounds.getX());
			}
		}else if(scroll.getX() > 0 && coordinates.getX() < (Crafex.getScreenWidth() * .4)){
			if(-movement.getX() <= scroll.getX()){
				scroll.addToX(movement.getX());
			}else{
				scroll.setX(0);
			}
		}
		if(scroll.getY() < bounds.getY() && coordinates.getY() > (Crafex.getScreenHeight() * .6)){
			if(movement.getY() <= bounds.getY() - scroll.getY() ){
				scroll.addToY(movement.getY());
			}else{
				scroll.setY(bounds.getY());
			}
		}else if(scroll.getY() > 0 && coordinates.getY() < (Crafex.getScreenHeight() * .4)){
			if(-movement.getY() <= scroll.getY()){
				scroll.addToY(movement.getY());
			}else{
				scroll.setY(0);
			}
		}
	}
	
	/**
	 * sets the location of the view of the map
	 * @param scroll
	 */
	public void setScroll(FloatVertex2D scroll){
		Level.scroll.setX(scroll.getX());
		Level.scroll.setY(scroll.getY());
	}
	
	/**
	 * resets the view to 0,0
	 */
	public void resetScroll(){
		scroll.reset();
	}
	
	/**
	 * holds default update for level. and should not be overriddin. use updateFirst() or updateLast()
	 */
	public void update(){
		updateFirst();
		
		
		
		updateLast();
	}
	
	/**
	 * used to update level items before the default update method items are called.
	 */
	public void updateFirst(){
		
	}
	
	/**
	 * used to update level items after the default update method items are called.
	 */
	public void updateLast(){
		
	}
	
	/**
	 * holds default drawing methods for level. and should not be overriddin. use updateFirst() or updateLast()
	 */
	public void draw(Canvas canvas){
		drawFirst(canvas);
		
		if(background != null){
			for(int w = 0; w - background.getWidth() < bounds.getX(); w += background.getWidth()){
	    		for(int h = 0; h - background.getHeight() < bounds.getY(); h += background.getHeight()){
	    			canvas.drawBitmap(background, w - scroll.getX(), h - scroll.getY(), null);
	    		}
	    	}
		}else{
//			paint.setColor(Color.BLACK);
			canvas.drawRect(0, 0, Crafex.getScreenWidth(), Crafex.getScreenHeight(), new Paint());
		}
		
		if(LevelHandler.isPlaying()){
			for(int i = 0; i < GUI.size(); i++){
				GUI.get(i).draw(canvas);
			}
		}else{
			for(int i = 0; i < LevelHandler.getPauseGUI().size(); i++){
				LevelHandler.getPauseGUI().get(i).draw(canvas);
			}
		}
		
		
		drawLast(canvas);
	}
	
	/**
	 * used to draw level items before the default update method items are called.
	 */
	public void drawFirst(Canvas canvas){
		
	}
	
	/**
	 * used to draw level items after the default update method items are called.
	 */
	public void drawLast(Canvas canvas){
		
	}
	
	public void buttonHandler(int keyCode){
		if(keyCode == KeyEvent.KEYCODE_ENDCALL){
			System.exit(0);
		}
	}
	
	/**
	 * handles inputs for level.
	 */
	public void inputHandler(MotionEvent event){
		if(event != null){
			if(event.getAction() == MotionEvent.ACTION_DOWN){
				
				if(LevelHandler.isPlaying()){
					for(int i = 0; i < getGUI().size(); i++){
						if(getGUI().get(i).isCollition(event.getX(), event.getY()) && System.currentTimeMillis() - lastTouchTime >= 900){
							Console.runCommand(LevelHandler.getGUI().get(i).getCommand());
							lastTouchTime = System.currentTimeMillis();
						}
					}
				}else{
					for(int i = 0; i < LevelHandler.getPauseGUI().size(); i++){
						if(LevelHandler.getPauseGUI().get(i).isCollition(event.getX(), event.getY())){
							Console.runCommand(LevelHandler.getPauseGUI().get(i).getCommand());
						}
					}
				}
			}
		}
	}
}
